<cfcomponent displayname="ArrayDriver" hint="This class is a dictionary driver to manager Array Object" output="false">
	<cfscript>
		/**
		* 	Domain random Method
		* 	@name random
		* 	@access public
		* 	@author Paulo Teixeira
		*	@date 2012-05-31
		*	@return Array
		**/
		public Array function random( Array problem ) {
			var arrDataSet 	   	= [];
			var totalItensArray = ArrayLen( arguments.problem );
			var indexRemove	   	= 0;

			for( var idx = 1; idx <= totalItensArray; idx++ ) {
				indexRemove  		= RandRange( 1, ( ( totalItensArray + 1 ) -idx ) );
				arrDataSet[ idx ] 	= arguments.problem[ indexRemove ];

				ArrayDeleteAt( arguments.problem , indexRemove );
			}

			return arrDataSet;
		}

		/**
		* 	cast data to array Method
		* 	@name asArray
		* 	@access public
		* 	@author Paulo Teixeira
		*	@date 2012-05-22
		*	@return Array
		**/
		public Array function asArray( Any data ) {
			var adapter = "";

			if( IsArray( arguments.data ) == true ) {
				return arguments.data;
			}
			else {
				adapter = this.getAdapter( data : arguments.data )
			}

			return adapter.asArray( data : arguments.data );
		}

		/**
		* 	Domain cast some array data to query Method
		* 	@name asQuery
		* 	@access public
		* 	@author Paulo Teixeira
		*	@date 2012-05-25
		*	@return Query
		**/
		public Query function asQuery( Array data ) {
			var rsDataSet  	= QueryNew("data");
			var arrayData  = arguments.data;
			var fieldList 	= "";
			var key			= "";

			// extract field names of the struct if exists
			if( ArrayLen( arrayData ) >= 1 ) {
				if( IsStruct( arrayData[1] ) ) {
					fieldList = LCase( StructKeyList( arrayData[1] ) );
				}
				else {
					fieldList = "data";
				}

				rsDataSet = QueryNew( fieldList );

				for( row in arrayData ) {
					QueryAddRow( rsDataSet );
					for( var idx = 1; idx <= ListLen( fieldList ); idx++ ){
						key = ListGetAt( fieldList , idx );
						QuerySetCell( rsDataSet , key , row[ key ] );
					}
				}
			}

			return rsDataSet;
		}

		/**
		* 	get an item of object Method
		* 	@name getItem
		* 	@access public
		* 	@author Paulo Teixeira
		*	@date 2012-05-28
		*	@return Array
		**/
		public Array function getItem( Array data , String field ,Any item ) {
			var arrDataSet	= [];
			var item		= arguments.item;
			var data		= arguments.data;
			var field		= arguments.field;
			var row			= [];

			for( row in data ) {
				if( Len( arguments.field ) > 0 ) {
					if( IsStruct( row ) == true ) {
						if( StructKeyExists( row , field ) == true ) {
							if( CompareNoCase( row[ field ] , item ) == 0 ) {
								variables.returnArrayIndex =  ArrayLen( arrDataSet ) + 1;
								arrDataSet[variables.returnArrayIndex] = {};
								arrDataSet[variables.returnArrayIndex][ field ] = row[ arguments.field ];
							}
						}
					}
					else {
						variables.error = Application.instance.factory.getModels("Error");
						variables.error.handlerError( Application.config.customExceptionUser , "The object data not is an array of struct" );
					}
				}
				else {
					if( CompareNoCase( row , item ) == 0 ) {
						variables.returnArrayIndex =  ArrayLen( arrDataSet ) + 1;
						arrDataSet[ variables.returnArrayIndex ] = row;
					}
				}
			}

			return arrDataSet;
		}

		/**
		* 	set data in the object Method
		* 	@name add
		* 	@access public
		* 	@author Paulo Teixeira
		*	@date 2012-05-28
		*	@return Array
		**/
		public Array function add( Array source , Array data ) {
			var arrDataSet	= arguments.source;
			var data		= arguments.data;

			arrDataSet.addAll( data );

			return arrDataSet;
		}

		/**
		* 	Domain determin sort field Method
		* 	@name asc
		* 	@access public
		* 	@author Paulo Teixeira
		*	@date 2012-05-29
		*	@return String
		**/
		public String function asc( field = "" ) {
			var order = "ASC";

			return order;
		}

		/**
		* 	Domain determin sort field Method
		* 	@name desc
		* 	@access public
		* 	@author Paulo Teixeira
		*	@date 2012-05-29
		*	@return String
		**/
		public String function desc( field = "" ) {
			var order = "DESC";

			return order;
		}

		/**
		* 	Domain sort data Method
		* 	@name sort
		* 	@access public
		* 	@author Paulo Teixeira
		*	@date 2012-05-29
		*	@return Array
		**/
		public Array function sort( Array recordSet , String filter ) {
			var arrRecordSet 	= {};
			var recordSet 		= arguments.recordSet;
			var filter 			= arguments.filter;

			arrRecordSet = ArraySort( recordSet , "text" , filter );

			return arrRecordSet;
		}

		/**
		* 	sum data from some attribute object Method
		* 	@name sumFrom
		* 	@access public
		* 	@author Paulo Teixeira
		*	@date 2012-05-29
		*	@return Array
		**/
		public Array function sumFrom( Array source , String data = "" ) {
			var arrDataSet	= [];
			var field 		= arguments.data;

			try{
				if( Len( field ) > 0  && IsStruct( arguments.source[1] ) == true ) {
					for( row in arguments.source ) {
						variables.tempArray = row[ field ];
					}

					arrDataSet[1] = ArraySum( variables.tempArray );
				}
				else {
					arrDataSet[1] = ArraySum( arguments.source );
				}
			}
			catch( Any Ex ) {
				variables.error = Application.instance.factory.getModels("Error");
				variables.error.handlerError( Application.config.customExceptionUser , "The object data contains some numeric value to sum data" );
			}

			return arrDataSet;
		}

		/**
		* 	Domain get adapter intance Method
		* 	@name getAdapter
		* 	@access private
		* 	@author Paulo Teixeira
		*	@date 2012-05-22
		*	@return Any
		**/
		private Any function getAdapter( Any data ) {
			if( IsQuery( arguments.data ) == true ) {
				return Application.instance.factory.getDitionary("QueryDriver");
			}
			else if( IsStruct( arguments.data ) == true ) {
				return Application.instance.factory.getDitionary("StructDriver");
			}
			else if( ListLen( arguments.data ) gt 0 ) {
				return Application.instance.factory.getDitionary("ListDriver");
			}
			else {
				variables.error = Application.instance.factory.getModels("Error");
				variables.error.handlerError( Application.config.customExceptionUser , "The object data not is in a valid data type or is empty" );
			}
		}

	</cfscript>
</cfcomponent>